/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-05-16     甘泽       the first version
 */

/*
 *
 * bmp280 数据手册关于 SPI 注意事项：
 *
 * 在SPI模式下，只使用寄存器地址的7位;寄存器地址的MSB不被使用，
 * 而是被一个读/写位(RW = ' 0 '为写，RW = ' 1 '为读)所取代。
 *
 * SPI write:
 * Writing is done by lowering CSB and sending pairs control bytes
 *  and register data. The control bytes consist of the SPI register
 *  address (= full register address without bit 7) and the write
 * command (bit7 = RW = ‘0’). Several pairs can be written without
 * raising CSB. The transaction is ended by a raising CSB.
 *
 *
 *
 * SPI read:
 * Reading is done by lowering CSB and first sending one control byte.
 * The control bytes consist of the SPI register address
 * (= full register address without bit 7) and the read command
 * (bit 7 = RW = ‘1’).After writing the control byte,
 *  data is sent out of the SDO pin (SDI in 3-wire mode);
 * the register address is automatically incremented.
 *
 */

#include <rtthread.h>
#include <rtdbg.h>

#include <sensor_bmp280.h>
#include <bmp280.h>

#include <stm32f4xx_hal.h>

// #define DBG_LEVEL DBG_INFO
#include <rtdbg.h>

static struct bmp280_dev bmp280_device;

static rt_device_t bmp280_baro_dev = RT_NULL;
static rt_device_t bmp280_temp_dev = RT_NULL;

static int rt_bmp280_sensor_register(void);
static int bsp_bmp280_init();

#ifndef BMP280_USING_SPI
static I2C_HandleTypeDef bmp280_i2c_handle;
static int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
static int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
#else
static SPI_HandleTypeDef bmp280_spi_handle;
static int8_t spi_reg_write(uint8_t spi_unused, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
static int8_t spi_reg_read(uint8_t spi_unused, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
#endif

static void bmp280_delay_ms(uint32_t period_ms);

/* device interface */
static rt_err_t rt_bmp280_baro_open(rt_device_t dev, rt_uint16_t oflag);
static rt_err_t rt_bmp280_baro_close(rt_device_t dev);
static rt_size_t rt_bmp280_baro_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
static rt_size_t rt_bmp280_baro_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);

static rt_err_t rt_bmp280_control(rt_device_t dev, int cmd, void *args);

static rt_err_t rt_bmp280_temp_open(rt_device_t dev, rt_uint16_t oflag);
static rt_err_t rt_bmp280_temp_close(rt_device_t dev);
static rt_size_t rt_bmp280_temp_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
static rt_size_t rt_bmp280_temp_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);

int start_bmp280(void)
{
    /* 第一步：注册传感器设备 */
    int rslt = rt_bmp280_sensor_register();
    if (rslt != RT_EOK)
        return rslt;

    /* 第二步：板级初始化 */
    rslt = bsp_bmp280_init();
    return rslt;
}

static int rt_bmp280_sensor_register(void)
{
    static rt_uint8_t bmp280_dev_register_passed = 0;
    if (bmp280_dev_register_passed != 0)
        return RT_EOK;

    /* construct device */
    bmp280_baro_dev = rt_device_create(RT_Object_Class_Device, 0);
    if (bmp280_baro_dev == RT_NULL)
    {
        rt_kprintf("error happened when create bmp280 baro device\n");
        return RT_ENOMEM;
    }

    bmp280_temp_dev = rt_device_create(RT_Object_Class_Device, 0);
    if (bmp280_temp_dev == RT_NULL)
    {
        rt_kprintf("error happened when create bmp280 temp device\n");
        return RT_ENOMEM;
    }

    /* set device function pointer */
    bmp280_baro_dev->init = RT_NULL;
    bmp280_baro_dev->open = rt_bmp280_baro_open;
    bmp280_baro_dev->close = rt_bmp280_baro_close;
    bmp280_baro_dev->read = rt_bmp280_baro_read;
    bmp280_baro_dev->write = rt_bmp280_baro_write;
    bmp280_baro_dev->control = rt_bmp280_control;

    bmp280_temp_dev->init = RT_NULL;
    bmp280_temp_dev->open = rt_bmp280_temp_open;
    bmp280_temp_dev->close = rt_bmp280_temp_close;
    bmp280_temp_dev->read = rt_bmp280_temp_read;
    bmp280_temp_dev->write = rt_bmp280_temp_write;
    bmp280_temp_dev->control = rt_bmp280_control;

    /* register device */
    rt_err_t rslt = rt_device_register(bmp280_baro_dev, "bmp280_baro", RT_DEVICE_FLAG_RDWR);
    rslt = rt_device_register(bmp280_temp_dev, "bmp280_temp", RT_DEVICE_FLAG_RDWR);
    if (rslt != RT_EOK)
    {
        LOG_E("error happened when register bmp280 baro device, rslt = %d\n", rslt);
        return rslt;
    }
    if (rslt != RT_EOK)
    {
        LOG_E("error happened when register bmp280 temp device, rslt = %d\n", rslt);
        return rslt;
    }

    bmp280_dev_register_passed = 1;
    return RT_EOK;
}

int bmp280_sensor_sample(void)
{
    rt_device_t bmp280_baro = rt_device_find("bmp280_baro");
    if (bmp280_baro == RT_NULL)
    {
        LOG_E("find bmp280_baro failed\n");
        return RT_ERROR;
    }

    rt_device_open(bmp280_baro, RT_DEVICE_FLAG_RDWR);
    rt_uint32_t baro_raw_data;

    for (int i = 0; i < 5; i++)
    {
        rt_device_read(bmp280_baro, 0, &baro_raw_data, 1);
        rt_kprintf("bmp280 raw barometer data = %d\n", baro_raw_data);
    }

    rt_device_close(bmp280_baro);

    return RT_EOK;
}
MSH_CMD_EXPORT(bmp280_sensor_sample, "bmp280_sensor_device_sample");

#ifdef BMP280_USING_I2C
/// @brief i2c low level init
/// @return
static int bmp280_i2c_msp_init()
{
    GPIO_InitTypeDef GPIO_InitStruct;

    /*##-1- Enable peripherals Clocks #################################*/
    BMP280_I2C_SCL_GPIO_RCC_ENABLE();
    BMP280_I2C_SDA_GPIO_RCC_ENABLE();
    BMP280_I2C_RCC_ENABLE();

    /*##-2- Configure peripheral GPIO ##########################################*/
    /* UART TX GPIO pin configuration  */
    GPIO_InitStruct.Pin = BMP280_I2C_SCL_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
    GPIO_InitStruct.Alternate = BMP280_I2C_SCL_AF;

    HAL_GPIO_Init(BMP280_I2C_SCL_GPIO, &GPIO_InitStruct);

    /* UART RX GPIO pin configuration  */
    GPIO_InitStruct.Pin = BMP280_I2C_SDA_PIN;
    GPIO_InitStruct.Alternate = BMP280_I2C_SDA_AF;

    HAL_GPIO_Init(BMP280_I2C_SDA_GPIO, &GPIO_InitStruct);

    I2C_InitTypeDef I2C_InitStruct;
    I2C_InitStruct.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    I2C_InitStruct.ClockSpeed = 100 * 1000;
    I2C_InitStruct.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    I2C_InitStruct.DutyCycle = I2C_DUTYCYCLE_2;
    I2C_InitStruct.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    I2C_InitStruct.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    I2C_InitStruct.OwnAddress1 = 0x01;

    bmp280_i2c_handle.Instance = BMP280_I2C;
    bmp280_i2c_handle.Init = I2C_InitStruct;
    bmp280_i2c_handle.MemaddSize = I2C_MEMADD_SIZE_8BIT;

    // HAL_I2CEx_ConfigAnalogFilter(&bmp280_i2c_handle, I2C_ANALOGFILTER_ENABLE);

    if (HAL_I2C_Init(&bmp280_i2c_handle) != HAL_OK)
        return RT_ERROR;

    __HAL_I2C_ENABLE(&bmp280_i2c_handle);

    return RT_EOK;
}
#endif

#ifdef BMP280_USING_SPI
/// @brief spi low level init
/// @return
static int bmp280_spi_msp_init()
{
    GPIO_InitTypeDef GPIO_InitStruct;

    /*##-1- Enable peripherals Clocks #################################*/
    BMP280_SPI_SCK_GPIO_RCC_ENABLE();
    BMP280_SPI_MISO_GPIO_RCC_ENABLE();
    BMP280_SPI_MOSI_GPIO_RCC_ENABLE();
    BMP280_SPI_CS_GPIO_RCC_ENABLE();

    BMP280_SPI_RCC_ENABLE();

    /*##-2- Configure peripheral GPIO ##########################################*/
    /* UART TX GPIO pin configuration  */
    GPIO_InitStruct.Pin = BMP280_SPI_SCK_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = BMP280_SPI_SCK_AF;

    HAL_GPIO_Init(BMP280_SPI_SCK_GPIO, &GPIO_InitStruct);

    /* UART RX GPIO pin configuration  */
    GPIO_InitStruct.Pin = BMP280_SPI_MOSI_PIN;
    GPIO_InitStruct.Alternate = BMP280_SPI_MOSI_AF;

    HAL_GPIO_Init(BMP280_SPI_MOSI_GPIO, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = BMP280_SPI_MISO_PIN;
    GPIO_InitStruct.Alternate = BMP280_SPI_MISO_AF;

    HAL_GPIO_Init(BMP280_SPI_MISO_GPIO, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = BMP280_SPI_CS_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    HAL_GPIO_Init(BMP280_SPI_CS_GPIO, &GPIO_InitStruct);

    bmp280_spi_handle.Instance = BMP280_SPI;
    bmp280_spi_handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
    bmp280_spi_handle.Init.Direction = SPI_DIRECTION_2LINES;
    bmp280_spi_handle.Init.CLKPhase = SPI_PHASE_1EDGE;
    bmp280_spi_handle.Init.CLKPolarity = SPI_POLARITY_LOW;
    bmp280_spi_handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    bmp280_spi_handle.Init.CRCPolynomial = 7;
    bmp280_spi_handle.Init.DataSize = SPI_DATASIZE_8BIT;
    bmp280_spi_handle.Init.FirstBit = SPI_FIRSTBIT_MSB;
    bmp280_spi_handle.Init.NSS = SPI_NSS_SOFT;
    bmp280_spi_handle.Init.TIMode = SPI_TIMODE_DISABLE;

    bmp280_spi_handle.Init.Mode = SPI_MODE_MASTER;

    if (HAL_SPI_Init(&bmp280_spi_handle) != HAL_OK)
    {
        return RT_ERROR;
    }

    __HAL_SPI_ENABLE(&bmp280_spi_handle);

    return RT_EOK;
}
#endif

/* bmp280 barometer device board init */
static int bsp_bmp280_init()
{
    /* i2c init */

    /* Map the delay function pointer with the function responsible for implementing the delay */
    bmp280_device.delay_ms = bmp280_delay_ms;

    /* Assign device I2C address based on the status of SDO pin (GND for PRIMARY(0x76) & VDD for SECONDARY(0x77)) */
    bmp280_device.dev_id = 0;

#ifndef BMP280_USING_SPI
    /* Select the interface mode as I2C */
    bmp280_device.intf = BMP280_I2C_INTF;

    /* Map the SPI read & write function pointer with the functions responsible for I2C bus transfer */
    // 在此将I2C读写寄存器函数更换为SPI读写寄存器函数
    bmp280_device.read = i2c_reg_read;
    bmp280_device.write = i2c_reg_write;
    bmp280_i2c_msp_init();
#else
/* Select the interface mode */
#ifdef BMP280_USING_SPI
    bmp280_device.intf = BMP280_SPI_INTF;
    bmp280_device.read = spi_reg_read;
    bmp280_device.write = spi_reg_write;
    bmp280_spi_msp_init();
#else
    bmp280_device.intf = BMP280_I2C_INTF;
    bmp280_device.read = i2c_reg_read;
    bmp280_device.write = i2c_reg_write;
    bmp280_i2c_msp_init();
#endif

#endif
    int rslt = bmp280_init(&bmp280_device);

    if (rslt != BMP280_OK)
    {
        LOG_E(" bmp280_init status = %d\n", rslt);
        return rslt;
    }
    /* Always read the current settings before writing, especially when
     * all the configuration is not modified
     */
    struct bmp280_config conf;
    rslt = bmp280_get_config(&conf, &bmp280_device);
    if (rslt != BMP280_OK)
    {
        LOG_E(" bmp280_get_config status = %d\n", rslt);
        return rslt;
    }

    /* configuring the temperature oversampling, filter coefficient and output data rate */
    /* Overwrite the desired settings */

    conf.filter = BMP280_FILTER_COEFF_2;
    /* Temperature oversampling set at 4x */

    conf.os_temp = BMP280_OS_4X;

    /* Pressure oversampling set at 4x */
    conf.os_pres = BMP280_OS_4X;

    /* Setting the output data rate as 8HZ(125ms) */
    conf.odr = BMP280_ODR_125_MS;
    rslt = bmp280_set_config(&conf, &bmp280_device);

    if (rslt != BMP280_OK)
    {
        LOG_E(" bmp280_set_config status = %d\n", rslt);
        return -RT_ERROR;
    }
    /* Always set the power mode after setting the configuration */
    rslt = bmp280_set_power_mode(BMP280_NORMAL_MODE, &bmp280_device);

    if (rslt != BMP280_OK)
    {
        LOG_E(" bmp280_set_power_mode status = %d\n", rslt);
        return -RT_ERROR;
    }
    return RT_EOK;
}

static rt_err_t rt_bmp280_baro_open(rt_device_t dev, rt_uint16_t oflag)
{
    if (dev == RT_NULL || dev != bmp280_baro_dev)
    {
        LOG_E("bmp280 barometer open failed for device pointer not correct\n");
        return RT_ERROR;
    }

    rt_uint8_t mode = 0xff;
    bmp280_get_power_mode(&mode, &bmp280_device);
    if (mode == BMP280_SLEEP_MODE || mode == BMP280_NORMAL_MODE || mode == BMP280_FORCED_MODE)
    {
        return RT_EOK;
    }

#ifdef BMP280_USING_I2C
    bmp280_i2c_msp_init();
#else
    bmp280_spi_msp_init();
#endif
    return RT_EOK;
}

static rt_err_t rt_bmp280_baro_close(rt_device_t dev)
{
    if (dev == RT_NULL || dev != bmp280_baro_dev)
    {
        LOG_E("bmp280 barometer close failed for device pointer not correct\n");
        return RT_ERROR;
    }

#ifdef BMP280_USING_I2C
    __HAL_I2C_DISABLE(&bmp280_i2c_handle);
    HAL_I2C_DeInit(&bmp280_i2c_handle);
#else
    __HAL_SPI_DISABLE(&bmp280_spi_handle);
    HAL_SPI_DeInit(&bmp280_spi_handle);
#endif

    return RT_EOK;
}

/// @brief
/// @param dev
/// @param pos
/// @param buffer
/// @param size
/// @return
static rt_size_t rt_bmp280_baro_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
    if (dev == RT_NULL || dev != bmp280_baro_dev)
    {
        LOG_E("bmp280 baro read device pointer not correct\n");
        return RT_ERROR;
    }

    struct bmp280_uncomp_data ucomp_data;
    uint32_t pres32;

    /* Reading the raw data from sensor */
    if (bmp280_get_uncomp_data(&ucomp_data, &bmp280_device) != BMP280_OK)
    {
        LOG_E("Reading the raw data from sensor error\n");
        return RT_ERROR;
    }

    /* Getting the compensated pressure using 32 bit precision */
    bmp280_get_comp_pres_32bit(&pres32, ucomp_data.uncomp_press, &bmp280_device);
    uint32_t *data_buf = (uint32_t *)buffer;
    *data_buf = pres32;

    return RT_EOK;
}

/// @brief
/// @param dev
/// @param pos reg address
/// @param buffer reg value
/// @param size
/// @return
static rt_size_t rt_bmp280_baro_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
    if (dev == RT_NULL || dev != bmp280_baro_dev)
    {
        LOG_E("bmp280 baro write device pointer not correct\n");
        return RT_ERROR;
    }

    bmp280_device.write(bmp280_device.chip_id, (uint8_t)pos, (uint8_t *)buffer, (uint16_t)size);
    return size;
}

static rt_err_t rt_bmp280_temp_open(rt_device_t dev, rt_uint16_t oflag)
{
    if (dev == RT_NULL || dev != bmp280_temp_dev)
    {
        LOG_E("bmp280 tempereture read device pointer not correct\n");
        return RT_ERROR;
    }

    rt_uint8_t mode = 0xff;
    bmp280_get_power_mode(&mode, &bmp280_device);
    if (mode == BMP280_SLEEP_MODE || mode == BMP280_NORMAL_MODE || mode == BMP280_FORCED_MODE)
    {
        return RT_EOK;
    }

    /* recover from close */
#ifndef BMP280_USING_SPI
    bmp280_i2c_msp_init();
#else
    bmp280_spi_msp_init();
#endif
    return RT_EOK;
}

static rt_err_t rt_bmp280_temp_close(rt_device_t dev)
{
    if (dev == RT_NULL || dev != bmp280_temp_dev)
    {
        LOG_E("bmp280 barometer close failed for device pointer not correct\n");
        return RT_ERROR;
    }

#ifndef BMP280_USING_SPI
    __HAL_I2C_DISABLE(&bmp280_i2c_handle);
    HAL_I2C_DeInit(&bmp280_i2c_handle);
#else
    __HAL_SPI_DISABLE(&bmp280_spi_handle);
    HAL_SPI_DeInit(&bmp280_spi_handle);
#endif

    return RT_EOK;
}

static rt_size_t rt_bmp280_temp_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
    struct bmp280_uncomp_data ucomp_data;
    int32_t temp32;

    /* Reading the raw data from sensor */
    if (bmp280_get_uncomp_data(&ucomp_data, &bmp280_device) != BMP280_OK)
    {
        LOG_E("Reading the raw data from sensor error");
        return RT_ERROR;
    }
    /* Getting the compensated pressure using 32 bit precision */
    bmp280_get_comp_temp_32bit(&temp32, ucomp_data.uncomp_temp, &bmp280_device);
    uint32_t *data_buf = (uint32_t *)buffer;
    *data_buf = temp32;

    return RT_EOK;
}

/// @brief
/// @param dev
/// @param pos reg address
/// @param buffer
/// @param size
/// @return
static rt_size_t rt_bmp280_temp_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
    if (dev == RT_NULL || dev != bmp280_temp_dev)
    {
        LOG_E("bmp280 baro read device pointer not correct\n");
        return RT_ERROR;
    }

    bmp280_device.write(bmp280_device.chip_id, (uint8_t)pos, (uint8_t *)buffer, (uint16_t)size);
    return size;
}

/* conrtol bmp280 device */

static rt_err_t bmp280_set_odr(rt_uint32_t odr)
{
    int8_t rslt;
    struct bmp280_config conf;

    rslt = bmp280_get_config(&conf, &bmp280_device);
    if (rslt != BMP280_OK)
    {
        LOG_E(" bmp280_get_config status = %d\n", rslt);
        return -RT_ERROR;
    }
    switch (odr)
    {
    case BMP280_ODR_1000_MS:
        conf.odr = BMP280_ODR_1000_MS;
        break;
    case BMP280_ODR_500_MS:
        conf.odr = BMP280_ODR_500_MS;
        break;
    case BMP280_ODR_250_MS:
        conf.odr = BMP280_ODR_250_MS;
        break;
    case BMP280_ODR_125_MS:
        conf.odr = BMP280_ODR_125_MS;
        break;
    case BMP280_ODR_62_5_MS:
        conf.odr = BMP280_ODR_62_5_MS;
        break;
    case BMP280_ODR_0_5_MS:
        conf.odr = BMP280_ODR_0_5_MS;
        break;
    case BMP280_ODR_2000_MS:
        conf.odr = BMP280_ODR_2000_MS;
        break;
    case BMP280_ODR_4000_MS:
        conf.odr = BMP280_ODR_4000_MS;
        break;

    default:
        return -RT_ERROR;
    }

    rslt = bmp280_set_config(&conf, &bmp280_device);

    if (rslt != BMP280_OK)
    {
        LOG_E("bmp280_set_config status = %d\n", rslt);
        return -RT_ERROR;
    }
    return RT_EOK;
}

static rt_err_t bmp280_set_pwr_mode(rt_uint32_t args)
{
    int8_t rslt;

    if (args != BMP280_SLEEP_MODE && args != BMP280_NORMAL_MODE && args != BMP280_FORCED_MODE)
    {
        rt_kprintf("bmp280_set_pwr_mode [%d] not match\n", args);
        return RT_ERROR;
    }

    rslt = bmp280_set_power_mode(args, &bmp280_device);

    return rslt;
}

static rt_err_t rt_bmp280_control(rt_device_t dev, int cmd, void *args)
{
    rt_uint32_t *val = (rt_uint32_t *)args;
    rt_err_t rslt = RT_EOK;
    switch (cmd)
    {
    case BMP280_CMD_SET_ODR:
        rslt = bmp280_set_odr(*val);
        break;

    case BMP280_CMD_SET_PWR_MODE:
        rslt = bmp280_set_pwr_mode(*val);
        break;

    default:
        break;
    }

    return rslt;
}

/*  bmp280 device control end */

/*!
 *  @brief Function that creates a mandatory delay required in some of the APIs such as "bmg250_soft_reset",
 *      "bmg250_set_foc", "bmg250_perform_self_test"  and so on.
 *
 *  @param[in] period_ms  : the required wait time in milliseconds.
 *  @return void.
 *
 */
static void bmp280_delay_ms(uint32_t period_ms)
{
    /* Implement the delay routine according to the target machine */
    rt_thread_mdelay(period_ms);
}

#ifdef BMP280_USING_I2C

/*!
 *  @brief Function for writing the sensor's registers through I2C bus.
 *
 *  @param[in] i2c_addr : sensor I2C address.
 *  @param[in] reg_addr : Register address.
 *  @param[in] reg_data : Pointer to the data buffer whose value is to be written.
 *  @param[in] length   : No of bytes to write.
 *
 *  @return Status of execution
 *  @retval 0 -> Success
 *  @retval >0 -> Failure Info
 *
 */
static int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
    /* Implement the I2C write routine according to the target machine. */

    HAL_StatusTypeDef rslt = HAL_I2C_Mem_Write(&bmp280_i2c_handle, i2c_addr, reg_addr, I2C_MEMADD_SIZE_8BIT, reg_data, length, length * 2);
    return rslt == HAL_OK ? RT_EOK : RT_ERROR;
}

/*!
 *  @brief Function for reading the sensor's registers through I2C bus.
 *
 *  @param[in] i2c_addr : Sensor I2C address.
 *  @param[in] reg_addr : Register address.
 *  @param[out] reg_data    : Pointer to the data buffer to store the read data.
 *  @param[in] length   : No of bytes to read.
 *
 *  @return Status of execution
 *  @retval 0 -> Success
 *  @retval >0 -> Failure Info
 *
 */
static int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
    /* Implement the I2C read routine according to the target machine. */
    HAL_StatusTypeDef rslt = HAL_I2C_Mem_Read(&bmp280_i2c_handle, i2c_addr, reg_addr, I2C_MEMADD_SIZE_8BIT, reg_data, length, length * 2);
    return rslt == HAL_OK ? RT_EOK : RT_ERROR;
}

#else

/*!
 *  @brief Function for writing the sensor's registers through SPI bus.
 *
 *  @param[in] spi_unused : sensor address, unused.
 *  @param[in] reg_addr : Register address.
 *  @param[in] reg_data : Pointer to the data buffer whose value is to be written.
 *  @param[in] length   : No of bytes to write.
 *
 *  @return Status of execution
 *  @retval 0 -> Success
 *  @retval >0 -> Failure Info
 *
 */
static int8_t spi_reg_write(uint8_t spi_unused, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
    // 使用SPI总线，先向BMP280发送寄存器地址，然后向寄存器写入数据
    HAL_GPIO_WritePin(BMP280_SPI_CS_GPIO, BMP280_SPI_CS_PIN, RESET);
    HAL_SPI_Transmit(&bmp280_spi_handle, &reg_addr, 1, 1);
    HAL_StatusTypeDef rslt = HAL_SPI_Transmit(&bmp280_spi_handle, reg_data, length, length * 5);
    HAL_GPIO_WritePin(BMP280_SPI_CS_GPIO, BMP280_SPI_CS_PIN, SET);
    return rslt == HAL_OK ? RT_EOK : RT_ERROR;
}

/*!
 *  @brief Function for reading the sensor's registers through I2C bus.
 *
 *  @param[in] spi_unused : Sensor address, unused.
 *  @param[in] reg_addr : Register address.
 *  @param[out] reg_data    : Pointer to the data buffer to store the read data.
 *  @param[in] length   : No of bytes to read.
 *
 *  @return Status of execution
 *  @retval 0 -> Success
 *  @retval >0 -> Failure Info
 *
 */
static int8_t spi_reg_read(uint8_t spi_unused, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
    HAL_GPIO_WritePin(BMP280_SPI_CS_GPIO, BMP280_SPI_CS_PIN, RESET);
    HAL_SPI_Transmit(&bmp280_spi_handle, &reg_addr, 1, 1);
    HAL_StatusTypeDef rslt = HAL_SPI_Receive(&bmp280_spi_handle, reg_data, length, length * 5);
    HAL_GPIO_WritePin(BMP280_SPI_CS_GPIO, BMP280_SPI_CS_PIN, SET);
    return rslt == HAL_OK ? RT_EOK : RT_ERROR;
}

#endif